
package com.deep.hystrix.command;

import com.deep.hystrix.service.TestService;
import com.netflix.hystrix.*;
import lombok.extern.slf4j.Slf4j;

import java.util.Random;

/**
 * 普通的HystrixCommand，实现了fallback方法
 */
@Slf4j
public class SimpleHystrixCommand extends HystrixCommand<String> {

    private TestService testService;

    public SimpleHystrixCommand(TestService testService) {
        super(setter());
        this.testService = testService;
    }

    @Override
    protected String run() throws Exception {
        String s = testService.getResult();
        log.info("get thread local:{}", s);

        /**
         * 如果睡眠时间，超过2s，会降级
         * {@link #getFallback()}
         */
        int millis = new Random().nextInt(3000);
        log.info("will sleep {} millis", millis);
        Thread.sleep(millis);

        return s;
    }

    private static Setter setter() {

        // 服务分组
        HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("members");
        // 服务标识
        HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("member");
        // 线程池名称
        HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("member-pool");

        // 线程池配置 线程池大小为10,线程存活时间15秒 队列等待的阈值为100,超过100执行拒绝策略
        HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter().withCoreSize(10)
                .withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100);

        // 命令属性配置Hystrix 开启超时
        HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
                // 采用线程池方式实现服务隔离
                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                /**
                 * 执行时间，2s，2s执行不完成，算超时，会降级
                 */
                .withExecutionTimeoutEnabled(true)
                .withExecutionTimeoutInMilliseconds(2000);

        return Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey)
                .andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties);

    }

    /**
     * 执行业务方法超时时，会进入本方法进行降级
     *
     * @return
     */
    @Override
    protected String getFallback() {

        log.error("fallback occur");
        return "fallback occur";
    }
}
